/**
 * 此脚本适合从MIT课程下载的HTML文件进行字幕转换
 * 提取字幕、生成ASS字幕文件、下载视频并提取音频
 * https://bigthink.com/
 */
const fs = require("fs");
const path = require("path");
const config = JSON.parse(fs.readFileSync(path.join(__dirname, "../..", "config.json"), "utf8"));
const { LocalSubtitleConverter } = require("./subtitleConverterLocal");

const { exec } = require("child_process");
const { FFMPEG_PATH } = require("./ffmpeg");
const mp3Dir = path.join(__dirname, "../..", config.inputDirMp3);

// 将主要逻辑封装为可重用的函数
async function convertHtmlToAss(htmlUrl, inputHtmlDir, outputAssPath) {
  const htmlDir = path.join(__dirname, "../..", inputHtmlDir);

  // 如果不存在htmlDir目录，则创建
  await ensureHtmlDirExists(htmlDir);

  const targetHtmlFile = "transcript.html";

  // 清理htmlDir目录
  await cleanHtmlDir(htmlDir, targetHtmlFile);

  // 如果配置了inputHtmlUrl,且inputHtmlUrl不为空
  // 则先从inputHtmlUrl对应的网页内容中解析class为transcript-body的dom的innerText
  console.log("  Parsing htmlUrl...");
  console.log("  htmlUrl: ", htmlUrl);
  let mediaID = null;
  if (htmlUrl && htmlUrl.trim() !== "") {
    const result = await parseHtmlContent(htmlUrl);
    mediaID = result.mediaID;

    if (mediaID) {
      await updateConfigTitle(result.mainTitle);
    }
  }
  console.log("  Parsing htmlUrl done.");

  // 如果有媒体下载链接，则下载媒体文件
  if (mediaID) {
    await downloadMediaFile(mediaID);
  }

  const videoPath = getVideoPath(mp3Dir, mediaID);
  console.log("  正在写入字幕文件...");
  await convertTxtToAss(videoPath, outputAssPath);
  console.log("  字幕文件生成完毕.");
}

// 确保HTML目录存在
function ensureHtmlDirExists(htmlDir) {
  if (!fs.existsSync(htmlDir)) {
    console.log(`  ${htmlDir} does not exist. Creating...`);
    fs.mkdirSync(htmlDir, { recursive: true });
  }
}

async function convertTxtToAss(videoPath, outputPath) {
  // 配置参数 - 请修改为实际路径
  // const videoPath = './input.mp4';
  // const transcriptPath = './transcript.txt';
  // const outputPath = './local_subtitles.ass';

  try {
    // 读取原始台词
    console.log("读取台词文本...");

    // 创建转换器实例并生成字幕
    const converter = new LocalSubtitleConverter();

    await converter.generateASSWithWhisper(videoPath, outputPath);

    console.log("  字幕生成完成!");
  } catch (error) {
    console.error("  处理失败:", error);
  }
}

// 清理HTML目录
function cleanHtmlDir(htmlDir, targetHtmlFile) {
  console.log("  Cleaning htmlDir...");
  if (htmlDir && htmlDir !== "") {
    const files = fs.readdirSync(htmlDir);
    files.forEach(file => {
      if (file !== targetHtmlFile) {
        fs.unlinkSync(path.join(htmlDir, file));
      }
    });
  }
}

// 解析HTML内容
async function parseHtmlContent(htmlUrl) {
  try {
    // 使用puppeteer加载页面并提取内容
    const puppeteer = require("puppeteer");
    const browser = await puppeteer.launch({
      headless: "new",
    });
    const page = await browser.newPage();
    await page.goto(htmlUrl, {
      waitUntil: "networkidle2",
      timeout: 60000,
    });

    // 等待transcript-body元素出现，最多等待10秒
    await page.waitForSelector(".prose-video", { timeout: 30000 });
    await page.waitForSelector(`div[x-show="current_tab === 'transcript'"]`, { timeout: 30000 });

    // 获取页面HTML内容
    await page.content();

    const infoDiv = await page.$(`div[class="relative w-full aspect-w-16 aspect-h-9 bg-black text-black-90 dark:text-white-90"]`);
    let mediaID = null;
    if(infoDiv){
      mediaData = await page.evaluate(el => el.getAttribute("x-data"), infoDiv);
      mediaID = eval(`(${mediaData})`)["media_id"];
    }
    if (mediaID) {
      console.log(`  Found media download link: ${mediaID}`);
    }

    // 当有 mediaDownloadLink 时，提取标题信息
    let mainTitle = "";
    try {
      // 获取主标题 (#course-banner下的h1)
      mainTitle = await page.$eval(`#primary div[class="flex w-full"] .card-content .card-headline`, el => el.innerText).catch(() => "");
    } catch (titleError) {
      console.warn("  Could not extract title elements:", titleError.message);
    }

    await browser.close();

    return {
      mediaID,
      mainTitle,
    };
  } catch (error) {
    console.error("  Error fetching or parsing HTML:", error);
    throw error;
  }
}

// 更新配置标题
function updateConfigTitle(mainTitle) {
  // 组合标题
  if (mainTitle) {
    mainTitle = mainTitle.substring(0, 30) + "...";
    const combinedTitle = `${mainTitle}`;

    // 更新 config.json 中的 title 属性
    const configPath = path.join(__dirname, "../..", "config.json");
    const configContent = JSON.parse(fs.readFileSync(configPath, "utf8"));
    configContent.title = combinedTitle;
    fs.writeFileSync(configPath, JSON.stringify(configContent, null, 2), "utf8");
    console.log(`  Updated config title to: ${combinedTitle}`);
  }
}

function getVideoPath(dir, mediaID) {
  return path.join(dir,`${mediaID}.mp4`);
}

// 下载媒体文件的函数，带重试机制
async function downloadMediaFile(mediaID) {
  // 清空config.inputDirMp3根目录的mp4文件，但不清空子文件夹
  if (fs.existsSync(mp3Dir)) {
    const files = fs.readdirSync(mp3Dir);
    let exist = false;
    files.forEach(function (file) {
      // 只删除根目录下的.mp4文件
      if (path.extname(file).toLowerCase() === ".mp4") {
        if(file.indexOf(mediaID) > -1) {
          exist = true;
          return;
        }
        const filePath = path.join(mp3Dir, file);
        const stat = fs.statSync(filePath);
        // 确保只删除根目录下的文件，而不是子文件夹中的文件
        if (stat.isFile()) {
          fs.unlinkSync(filePath);
          console.log("  Deleted existing mp4 file: " + file);
        }
      }
    });
    if (exist) {
      return;
    }
  } else {
    // 如果目录不存在，则创建它
    fs.mkdirSync(mp3Dir, { recursive: true });
  }

  console.log("  Downloading media file from: " + mediaID);

  // 构造输出文件路径
  const outputPath = getVideoPath(mp3Dir, mediaID);
  
  // 确保mp3Dir目录存在
  if (!fs.existsSync(mp3Dir)) {
    fs.mkdirSync(mp3Dir, { recursive: true });
    console.log(`  Created directory: ${mp3Dir}`);
  }
  
  // 构建m3u8 URL
  const m3u8Url = `https://cdn.jwplayer.com/manifests/${mediaID}.m3u8`;
  
  try {
    console.log("  尝试使用m3u8Downloader模块下载...");
    
    // 使用新的m3u8Downloader模块下载m3u8文件
    const { downloadM3U8Manifest } = require('./m3u8Downloader');
    const m3u8Content = await downloadM3U8Manifest(mediaID);
    
    console.log("  M3U8 Content:");
    // 只显示前500个字符以避免日志过长
    console.log(m3u8Content.substring(0, 500) + (m3u8Content.length > 500 ? '...' : ''));
    
    // 解析m3u8内容找到最高质量的流
    const lines = m3u8Content.split(/\r?\n/);
    let maxBandwidth = 0;
    let bestStreamUrl = "";
    
    for (let i = 0; i < lines.length; i++) {
      if (lines[i].match("#EXT-X-STREAM-INF")) {
        // 提取带宽信息
        const bandwidthMatch = lines[i].match(/BANDWIDTH=(\d+)/);
        if (bandwidthMatch) {
          const bandwidth = parseInt(bandwidthMatch[1]);
          console.log(`  Found stream with bandwidth: ${bandwidth}`);
          if (bandwidth > maxBandwidth) {
            maxBandwidth = bandwidth;
            // 下一行应该是URL
            if (i + 1 < lines.length) {
              bestStreamUrl = lines[i + 1].trim();
              console.log(`  Found better quality stream: ${bestStreamUrl}`);
            }
          }
        }
      }
    }
    
    // 如果是相对URL，需要转换为绝对URL
    if (bestStreamUrl && !bestStreamUrl.startsWith('http')) {
      const m3u8UrlObj = new URL(m3u8Url);
      bestStreamUrl = new URL(bestStreamUrl, m3u8UrlObj.origin + m3u8UrlObj.pathname).href;
      console.log(`  Resolved relative URL to: ${bestStreamUrl}`);
    }
    
    // 继续执行后续的流解析和下载逻辑...
    
    // 如果找到流URL，则下载
    if (bestStreamUrl !== "") {
      console.log(`  Downloading stream with bandwidth ${maxBandwidth} from ${bestStreamUrl}`);
      
      console.log(`  FFMPEG path: ${FFMPEG_PATH}`);
      console.log(`  Output path: ${outputPath}`);
      
      // 使用ffmpeg下载最高质量的流
      await new Promise((resolve, reject) => {
        const command = `"${FFMPEG_PATH}" -i "${bestStreamUrl}" -c copy -bsf:a aac_adtstoasc "${outputPath}" -headers "Referer: https://bigthink.com/"`;
        console.log(`  Executing command: ${command}`);
        
        exec(command, { 
          maxBuffer: 1024 * 1024 * 100, 
          cwd: mp3Dir 
        }, (error, stdout, stderr) => {
          if (error) {
            console.error("  FFmpeg download failed: " + error.message,error.code,stderr);
            reject(error);
          } else {
            console.log("  FFmpeg download success,stdout:",stdout);
            
            // 检查文件是否创建成功
            if (fs.existsSync(outputPath)) {
              const fileInfo = fs.statSync(outputPath);
              console.log(`  Output file size: ${fileInfo.size} bytes`);
              resolve(true);
            } else {
              reject(new Error(`Output file was not created: ${outputPath}`));
            }
          }
        });
      });
      
      return true;
    } else {
      throw new Error("No stream found in m3u8 manifest");
    }
  } catch (error) {
    console.error("  Puppeteer下载失败:", error.message);
    process.exit(1);
  }
}
// 保持向后兼容的主函数
async function main() {
  try {
    const textStyles = config.projectSettings?.textStyles || {};
    await convertHtmlToAss(config.inputHtmlUrl_Bigthink, config.inputDirHtml, path.join(config.inputDirDat, "transcript.ass"), textStyles);
  } catch (error) {
    console.error("转换过程中出现错误:", error);
    process.exit(1);
  }
}

// 如果直接运行此脚本，则执行main函数
if (require.main === module) {
  main();
}